
import UIKit
protocol DefaultValue {
    static var defaultValue: Self { get set}
}
// MARK: Dictionary默认值扩展
extension Dictionary: DefaultValue where Key: Codable, Value: DefaultValue {
    static var defaultValue: Dictionary<Key, Value> {
        get {
            return [Key: Value]()
        }
        set {
            
        }
     }
}



extension String: DefaultValue {
   static var  defaultValue = ""
}

extension Int: DefaultValue {
    static var defaultValue = 0
}
extension Float: DefaultValue {
    static var defaultValue:Float = 0.0
}
extension Bool: DefaultValue {
    static var defaultValue:Bool = false
}
extension Double: DefaultValue {
    static var defaultValue:Double = 0.0
}
extension CGFloat: DefaultValue {
    static var defaultValue:CGFloat = 0.0
}

typealias DefaultCodable = DefaultValue & Codable

//extension Dictionary:DefaultValue{
//    static var defaultValue:[String:Any] = [String:Any]()
//}

@propertyWrapper
struct Default<T: DefaultCodable> {
    var wrappedValue: T
}

extension Default: Codable {
    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if T.defaultValue is String{
            if let value  = try? container.decode(Int.self){
                T.defaultValue = String(value) as! T
            }else if let value = try? container.decode(Bool.self){
                T.defaultValue = (value == true ? "0" : "1") as! T
            }else if let value = try? container.decode(Double.self){
                T.defaultValue = String(value) as! T
            }else if let value = try? container.decode(Float.self){
                T.defaultValue = String(value) as! T
            }
        }else if T.defaultValue is Int{
            if let value  = try? container.decode(Int.self){
                T.defaultValue = Int(value) as! T
            }else
            if let value = try? container.decode(Bool.self){
                T.defaultValue = (value == true ? 0 : 1) as! T
            }else if let value = try? container.decode(Double.self){
                T.defaultValue = Int(value) as! T
            }else if let value = try? container.decode(Float.self){
                T.defaultValue = Int(value) as! T
            }else if let value = try? container.decode(String.self){
                T.defaultValue = String(value) as! T
            }
        }else if T.defaultValue is Float{
            if let value  = try? container.decode(Int.self){
                T.defaultValue = Float(value) as! T
            }else if let value = try? container.decode(Double.self){
                T.defaultValue = Float(value) as! T
            }else if let value = try? container.decode(Float.self){
                T.defaultValue = Float(value) as! T
            }
            else if let value = try? container.decode(String.self){
                T.defaultValue = String(value) as! T
            }
        }else if T.defaultValue is CGFloat{
            if let value  = try? container.decode(Int.self){
                T.defaultValue = CGFloat(value) as! T
            }else if let value = try? container.decode(Double.self){
                T.defaultValue = CGFloat(value) as! T
            }else if let value = try? container.decode(Float.self){
                T.defaultValue = CGFloat(value) as! T
            }
            else if let value = try? container.decode(String.self){
                let double = Double(value)
                T.defaultValue = CGFloat(double ?? 0.00) as! T
            }
        }
        else if T.defaultValue is Bool{
            if let value  = try? container.decode(Int.self){
                T.defaultValue = (value == 0 ? false : true) as! T
            }
            else if let value = try? container.decode(String.self){
                T.defaultValue = (value == "0" ? false : true) as! T
            }
        }
        
        wrappedValue = (try? container.decode(T.self)) ?? T.defaultValue
      // print(wrappedValue)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        try container.encode(wrappedValue)
    }
}


extension KeyedDecodingContainer {
    func decode<T>(_ type: Default<T>.Type, forKey key: KeyedDecodingContainer<K>.Key) throws -> Default<T> where T : DefaultCodable {
        try decodeIfPresent(type, forKey: key) ?? Default(wrappedValue: T.defaultValue)
    }
}


extension UnkeyedDecodingContainer {
    mutating func decode<T>(_ type: Default<T>.Type) throws -> Default<T> where T : DefaultCodable {
        try decodeIfPresent(type) ?? Default(wrappedValue: T.defaultValue)
    }
    
}
//struct Student:Codable{
//    @Default var name:String
//    @Default var age:Int
//}




struct DefaultArray<T:Codable>:Codable{
    private(set) var contens:[T] = [T]()
    var data:String?
    init(from decoder: Decoder) throws {
        var unkeyedContaines:UnkeyedDecodingContainer! = nil
        if  let  container = try? decoder.container(keyedBy:CodingKeys.self) {
            unkeyedContaines = try?
                container.nestedUnkeyedContainer(forKey:CodingKeys.data)
            print("")
        }else{
            unkeyedContaines = try decoder.unkeyedContainer()
        }
        guard unkeyedContaines != nil else{
            print("解析失败")
            return
        }
        print("解析成功")
        while !unkeyedContaines.isAtEnd {
            let a = try unkeyedContaines.decode(T.self)
            self.contens.append(a)
        }
    }
}


struct JSONConver<T:Codable>{
    //字典转模型
    static func model(_ dic:[String:Any]) -> T{
        let data = try! JSONSerialization.data(withJSONObject: dic)
        let jsondecoder = JSONDecoder()
        //jsondecoder.dataDecodingStrategy = JSONDecoder.secondsSince1970
        let item = try! jsondecoder.decode(T.self, from: data)
        return item
    }
    //key:data ,value任意一数组，如果你想更改key为别的字段，需要把以上DefaultArray的var data:String?更改自己需要的
    static func modelArray(_ array:[Any]) -> [T]{
       let data = try! JSONSerialization.data(withJSONObject: array)
       let jsondecoder = JSONDecoder()
        let arr = try! jsondecoder.decode(DefaultArray<T>.self, from: data).contens
        return arr
    }
    //字典数组转模型数组
    static func modelArray(_ dic:[String:Any]) -> [T]{
       let data = try! JSONSerialization.data(withJSONObject: dic)
       let jsondecoder = JSONDecoder()
        let arr = try! jsondecoder.decode(DefaultArray<T>.self, from: data).contens
        return arr
    }
    
}
